package admin

import (
	"go-amis-admin/amis"
	"html/template"
	"strings"

	"github.com/casbin/casbin/v2"
	"github.com/gin-gonic/gin"
	"gorm.io/driver/mysql"
	"gorm.io/driver/postgres"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
)

type App struct {
	Config *Config
	Sites  []*Site
	Router *gin.Engine
	DB     *gorm.DB
	Auth   *casbin.Enforcer
}

var Instance *App

func NewApp(cfg *Config) *App {
	router := gin.Default()
	db, err := initDB(cfg.DB)
	if err != nil {
		panic("connect database error:" + err.Error())
	}
	Instance = &App{
		Config: cfg,
		Router: router,
		Sites:  make([]*Site, 0),
		DB:     db,
		Auth:   InitCasbin(db),
	}

	//router.LoadHTMLGlob("templates/*.html")
	//router.Static("/static", "./templates/static")
	router.GET("/login", func(c *gin.Context) {
		tpl, err := template.New("login.html").Parse(amis.LoginTpl)
		if err != nil {
			c.String(500, err.Error())
			return
		}
		var ret strings.Builder
		err = tpl.Execute(&ret, gin.H{})
		if err != nil {
			c.String(500, err.Error())
			return
		}
		c.Header("Content-Type", "text/html")
		c.String(200, ret.String())
		//c.HTML(200, "login.html", gin.H{})
	})
	router.POST("/login", func(c *gin.Context) {
		var loginForm struct {
			Username string `form:"username"`
			Password string `form:"password"`
		}
		if err := c.ShouldBind(&loginForm); err != nil {
			c.JSON(200, gin.H{
				"status": 1,
				"msg":    "参数错误",
			})
			return
		}
		info, err := LoginCheck(loginForm.Username, loginForm.Password)
		if err != nil {
			c.JSON(200, gin.H{
				"status": 1,
				"msg":    err.Error(),
			})
			return
		}
		c.JSON(200, gin.H{
			"status": 0,
			"data":   info,
		})
	})

	router.GET("/logout", func(ctx *gin.Context) {

	})
	return Instance
}

func (a *App) RegisterSite(site *Site) {
	a.Sites = append(a.Sites, site)
	site.initModule()
}

func (a *App) DefaultSite() *Site {
	site := NewSite("系统", "admin", "index.html", 0, a.Router.Group("admin"))
	a.RegisterSite(site)
	return site
}

func (a *App) Run() {
	a.Router.Run()
}

func initDB(cfg DBConfig) (*gorm.DB, error) {
	var db *gorm.DB
	var err error
	config := gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
		NamingStrategy: schema.NamingStrategy{
			NoLowerCase: true,
		},
	}
	switch cfg.DbType {
	case "mysql":
		db, err = gorm.Open(mysql.New(mysql.Config{
			DSN: cfg.Dsn,
		}), &config)
	case "postgres":
		db, err = gorm.Open(postgres.Open(cfg.Dsn), &config)
	default:
		db, err = gorm.Open(sqlite.Open(cfg.Dsn), &config)
	}

	return db, err
}
